package cn.mw.cmdb.link.service.impl;


import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.link.entity.LinkLabelDto;
import cn.mw.cmdb.link.entity.MwNetWorkLinkDto;
import cn.mw.cmdb.link.enums.LinkDetectionWayEnum;
import cn.mw.cmdb.link.enums.LinkFetchPortEnum;
import cn.mw.cmdb.link.param.LinkParam;
import cn.mw.cmdb.link.service.MwNetWorkLinkService;
import cn.mw.cmdb.mongoMapper.MwNetWorkLinkMapper;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.microMonitorCommon.api.cmdb.MwNetWorkLinkCommonService;
import cn.mw.microMonitorCommon.entity.cmdb.MwNetWorkLinkInfo;
import cn.mw.microMonitorCommon.param.NetWorkLinkParam;
import cn.mw.microMonitorCommon.utils.DatabaseUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description 线路公共接口实现
 */
@DubboService
@Slf4j
public class MwNetWorkLinkCommonApiImpl implements MwNetWorkLinkCommonService {

    private MwNetWorkLinkMapper netWorkLinkMapper;

    private CmdbServiceManage cmdbServiceManage;

    private MwNetWorkLinkService netWorkLinkService;


    public MwNetWorkLinkCommonApiImpl(MwNetWorkLinkMapper netWorkLinkMapper,CmdbServiceManage cmdbServiceManage,MwNetWorkLinkService netWorkLinkService) {
        this.netWorkLinkMapper = netWorkLinkMapper;
        this.cmdbServiceManage = cmdbServiceManage;
        this.netWorkLinkService = netWorkLinkService;
    }

    @Override
    public List<MwNetWorkLinkInfo> getLinkInfo(NetWorkLinkParam linkParam) throws Exception {
        List<MwNetWorkLinkInfo> netWorkLinkInfos = new ArrayList<>();
        Criteria criteria = new Criteria();
        List<Criteria> orCriteria = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(linkParam.getLinkNames())) {
            Criteria nameCriteria = new Criteria().andOperator(Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getLinkName)).in(linkParam.getLinkNames()));
            orCriteria.add(nameCriteria);
        }
        if (CollectionUtils.isNotEmpty(linkParam.getTargetIps())) {
            Criteria ipCriteria = new Criteria().andOperator(Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getDetectionTargetIp)).in(linkParam.getTargetIps()));
            orCriteria.add(ipCriteria);
        }
        if(StringUtils.isNotEmpty(linkParam.getAssetsId()) && StringUtils.isNotEmpty(linkParam.getInterfaceName())){
            Criteria rootCriteria = new Criteria().andOperator(Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getSourceDeviceAsset)).is(linkParam.getAssetsId()),
                    Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getSourceDevicePort)).is(linkParam.getInterfaceName()),
                    Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getTakeValuePort)).is(LinkFetchPortEnum.ROOT.getType()));
            orCriteria.add(rootCriteria);
            Criteria targetCriteria = new Criteria().andOperator( Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getTargetDeviceAsset)).is(linkParam.getAssetsId()),
                    Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getTargetDevicePort)).is(linkParam.getInterfaceName()),
                    Criteria.where(DatabaseUtils.getColumnName(MwNetWorkLinkDto::getTakeValuePort)).is(LinkFetchPortEnum.TARGET.getType()));
            orCriteria.add(targetCriteria);
        }
        if(CollectionUtils.isEmpty(orCriteria)){
            return netWorkLinkInfos;
        }
        criteria.orOperator(orCriteria);
        Query query = new Query(criteria);
        List<MwNetWorkLinkDto> linkDtos = netWorkLinkMapper.find(query);
        if (CollectionUtils.isEmpty(linkDtos)) {
            return netWorkLinkInfos;
        }
        for (MwNetWorkLinkDto linkDto : linkDtos) {
            MwNetWorkLinkInfo netWorkLinkInfo = new MwNetWorkLinkInfo();
            netWorkLinkInfo.setLinkId(linkDto.getLinkId());
            netWorkLinkInfo.setLinkName(linkDto.getLinkName());
            netWorkLinkInfo.setTargetIp(linkDto.getDetectionTargetIp());
            if (StringUtils.isNotEmpty(linkDto.getDetectionWay()) && !linkDto.getDetectionWay().equals(LinkDetectionWayEnum.NOT_HAVE.getType())) {
                netWorkLinkInfo.setLinkType(linkDto.getDetectionWay());
            }
            //设置接口信息
            setInterfaceInfo(linkDto, netWorkLinkInfo);
            //设置标签信息
            setLabelInfo(linkDto, netWorkLinkInfo);
            netWorkLinkInfos.add(netWorkLinkInfo);
        }
        return netWorkLinkInfos;
    }

    @Override
    public List<MwNetWorkLinkInfo> getLinkMonitorInfo() {
        List<MwNetWorkLinkInfo> netWorkLinkInfos = new ArrayList<>();
        try {
            LinkParam linkParam = new LinkParam();
            linkParam.setPageNum(1);
            linkParam.setPageSize(Integer.MAX_VALUE);
            //查询线路
            Page page = netWorkLinkService.selectList(linkParam);
            List records = page.getRecords();
            if(CollectionUtils.isEmpty(records)){
                return netWorkLinkInfos;
            }
            List<MwNetWorkLinkDto> linkDtos = JSONArray.parseArray(JSON.toJSONString(records), MwNetWorkLinkDto.class);
            for (MwNetWorkLinkDto linkDto : linkDtos) {
                MwNetWorkLinkInfo netWorkLinkInfo = new MwNetWorkLinkInfo();
                netWorkLinkInfo.setLinkId(linkDto.getLinkId());
                netWorkLinkInfo.setLinkName(linkDto.getLinkName());
                netWorkLinkInfo.setTargetIp(linkDto.getDetectionTargetIp());
                netWorkLinkInfo.setInLinkBandwidthUtilization(linkDto.getInLinkBandwidthUtilization() == null?0:linkDto.getInLinkBandwidthUtilization());
                netWorkLinkInfo.setOutLinkBandwidthUtilization(linkDto.getOutLinkBandwidthUtilization() == null?0:linkDto.getOutLinkBandwidthUtilization());
                if (StringUtils.isNotEmpty(linkDto.getDetectionWay()) && !linkDto.getDetectionWay().equals(LinkDetectionWayEnum.NOT_HAVE.getType())) {
                    netWorkLinkInfo.setLinkType(linkDto.getDetectionWay());
                }
                //设置接口信息
                setInterfaceInfo(linkDto, netWorkLinkInfo);
                //设置标签信息
                setLabelInfo(linkDto, netWorkLinkInfo);
                netWorkLinkInfos.add(netWorkLinkInfo);
            }
        } catch (Throwable e) {
            log.error("MwNetWorkLinkCommonApiImpl{} getLinkMonitorInfo() error",e);
        }
        return netWorkLinkInfos;
    }

    @Override
    public MwNetWorkLinkInfo getIcmpTypeAssetsInfo() {
        MwNetWorkLinkInfo workLinkInfo = new MwNetWorkLinkInfo();
        List<MwNetWorkLinkDto> linkDtos = netWorkLinkMapper.findAll();
        if(CollectionUtils.isEmpty(linkDtos)){
            return workLinkInfo;
        }
        List<String> targetAssetsIds = linkDtos.stream().filter(item -> StringUtils.isNotEmpty(item.getDetectionTargetIpId())).map(s -> s.getDetectionTargetIpId()).collect(Collectors.toList());
        workLinkInfo.setIcmpAssetsIds(targetAssetsIds);
        return workLinkInfo;
    }

    private void setLabelInfo(MwNetWorkLinkDto linkDto, MwNetWorkLinkInfo netWorkLinkInfo) {
        List<LinkLabelDto> associationData = linkDto.getAssociationData();
        if (CollectionUtils.isEmpty(associationData)) {
            return;
        }
        Map<String, Object> dataMap = new HashMap<>();
        for (LinkLabelDto linkLabelDto : associationData) {
            dataMap.put(linkLabelDto.getLabel(), linkLabelDto.getData());
        }
        netWorkLinkInfo.setDetailData(dataMap);
    }

    private void setInterfaceInfo(MwNetWorkLinkDto linkDto, MwNetWorkLinkInfo netWorkLinkInfo) {
        String takeValuePort = linkDto.getTakeValuePort();
        if (StringUtils.isEmpty(takeValuePort)) {
            return;
        }
        String instanceId = null;
        LinkFetchPortEnum portEnum = LinkFetchPortEnum.getLinkFetchPortEnum(takeValuePort);
        switch (portEnum) {
            case ROOT:
                netWorkLinkInfo.setInterfaceName(linkDto.getSourceDevicePort());
                netWorkLinkInfo.setInterfaceIpAddress(linkDto.getSourceDeviceIp());
                instanceId = linkDto.getSourceDeviceAsset();
                break;
            case TARGET:
                netWorkLinkInfo.setInterfaceName(linkDto.getTargetDevicePort());
                netWorkLinkInfo.setInterfaceIpAddress(linkDto.getTargetDeviceIp());
                instanceId = linkDto.getTargetDeviceAsset();
        }
        if(StringUtils.isNotEmpty(instanceId)){
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceInfo instanceInfo = instanceService.getInstanceInfoById(instanceId);
            if(instanceInfo != null){
                netWorkLinkInfo.setDeviceName(instanceInfo.getInstanceName());
            }
        }
    }
}
